From 225da2d6cf45863d8c51aa59c1fa8134166f0563 Mon Sep 17 00:00:00 2001 From: "cl349@freefall.cl.cam.ac.uk" Date: Wed, 10 Nov 2004 11:00:27 +0000 Subject: [PATCH] bitkeeper revision 1.1159.1.399 (4191f4cbUvkMenqLkHaeRu45RztOdA) More SMP guest support. --- .../arch/xen/i386/kernel/cpu/common.c | 11 - .../arch/xen/i386/kernel/head.S | 24 +- .../arch/xen/i386/kernel/smp.c | 20 +- .../arch/xen/i386/kernel/smpboot.c | 246 +++++++++++++++--- .../arch/xen/kernel/evtchn.c | 28 +- .../drivers/xen/blkback/blkback.c | 1 + .../drivers/xen/blkfront/blkfront.c | 1 + .../drivers/xen/evtchn/evtchn.c | 1 + .../drivers/xen/netback/netback.c | 1 + .../asm-xen/asm-i386/mach-xen/smpboot_hooks.h | 3 + .../include/asm-xen/asm-i386/system.h | 1 - .../include/asm-xen/evtchn.h | 15 +- .../include/asm-xen/hypervisor.h | 20 ++ tools/libxc/xc_linux_restore.c | 14 +- xen/arch/x86/domain.c | 3 +- xen/arch/x86/x86_32/entry.S | 1 + xen/arch/x86/x86_32/mm.c | 17 +- xen/common/domain.c | 75 +++++- xen/common/keyhandler.c | 12 +- xen/common/sched_bvt.c | 40 +-- xen/common/schedule.c | 94 ++++--- xen/include/asm-x86/processor.h | 2 +- xen/include/public/xen.h | 3 +- xen/include/xen/event.h | 2 +- xen/include/xen/sched.h | 5 +- 25 files changed, 497 insertions(+), 143 deletions(-) diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/common.c b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/common.c index 2a2322d80e..524f2f4d46 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/common.c +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/common.c @@ -548,17 +548,6 @@ void __init cpu_init (void) set_in_cr4(X86_CR4_TSD); } - /* - * Initialize the per-CPU GDT with the boot GDT, - * and set up the GDT descriptor: - */ - if (cpu) { - cpu_gdt_descr[cpu].size = GDT_SIZE; - cpu_gdt_descr[cpu].address = 0; /* XXXcl alloc page */ - BUG(); /* XXXcl SMP */ - memcpy((void *)cpu_gdt_descr[cpu].address, - (void *)cpu_gdt_descr[0].address, GDT_SIZE); - } /* * Set up the per-thread TLS descriptor cache: */ diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/head.S b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/head.S index 1259369c03..57a7bd74af 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/head.S +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/head.S @@ -33,14 +33,19 @@ ENTRY(startup_32) cld - /* Set up the stack pointer */ - lss stack_start,%esp - /* Copy the necessary stuff from xen_start_info structure. */ mov $xen_start_info_union,%edi mov $128,%ecx rep movsl +#ifdef CONFIG_SMP +ENTRY(startup_32_smp) + cld +#endif /* CONFIG_SMP */ + + /* Set up the stack pointer */ + lss stack_start,%esp + checkCPUtype: /* get vendor info */ @@ -63,11 +68,22 @@ checkCPUtype: movb %cl,X86_MASK movl %edx,X86_CAPABILITY + incb ready + xorl %eax,%eax # Clear FS/GS and LDT movl %eax,%fs movl %eax,%gs cld # gcc2 wants the direction flag cleared at all times +#ifdef CONFIG_SMP + movb ready, %cl + cmpb $1,%cl + je 1f # the first CPU calls start_kernel + # all other CPUs call initialize_secondary + call initialize_secondary + jmp L6 +1: +#endif /* CONFIG_SMP */ call start_kernel L6: jmp L6 # main should never return here, but @@ -90,6 +106,8 @@ ENTRY(stack_start) .long init_thread_union+THREAD_SIZE .long __BOOT_DS +ready: .byte 0 + # XXXcl .globl idt_descr .globl cpu_gdt_descr diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smp.c b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smp.c index 31b4ed6838..0c0260daf2 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smp.c +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smp.c @@ -26,6 +26,8 @@ #include #endif +#define xxprint(msg) HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg) + /* * Some notes on x86 processor bugs affecting SMP operation: * @@ -126,7 +128,7 @@ static inline int __prepare_ICR2 (unsigned int mask) void __send_IPI_shortcut(unsigned int shortcut, int vector) { #if 1 - printk("__send_IPI_shortcut\n"); + xxprint("__send_IPI_shortcut\n"); #else /* * Subtle. In the case of the 'never do double writes' workaround @@ -165,7 +167,8 @@ void fastcall send_IPI_self(int vector) void send_IPI_mask_bitmask(cpumask_t cpumask, int vector) { #if 1 - printk("send_IPI_mask_bitmask\n"); + xxprint("send_IPI_mask_bitmask\n"); + dump_stack(); #else unsigned long mask = cpus_addr(cpumask)[0]; unsigned long cfg; @@ -201,7 +204,7 @@ void send_IPI_mask_bitmask(cpumask_t cpumask, int vector) inline void send_IPI_mask_sequence(cpumask_t mask, int vector) { #if 1 - printk("send_IPI_mask_sequence\n"); + xxprint("send_IPI_mask_sequence\n"); #else unsigned long cfg, flags; unsigned int query_cpu; @@ -349,7 +352,7 @@ asmlinkage void smp_invalidate_interrupt (void) leave_mm(cpu); } #if 1 - printk("smp_invalidate_interrupt ack_APIC_irq\n"); + xxprint("smp_invalidate_interrupt ack_APIC_irq\n"); #else ack_APIC_irq(); #endif @@ -405,6 +408,7 @@ static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm, */ send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR); + xxprint("flush_tlb_others lockup"); while (!cpus_empty(flush_cpumask)) /* nothing. lockup detection does not belong here */ mb(); @@ -574,7 +578,7 @@ static void stop_this_cpu (void * dummy) cpu_clear(smp_processor_id(), cpu_online_map); local_irq_disable(); #if 1 - printk("stop_this_cpu disable_local_APIC\n"); + xxprint("stop_this_cpu disable_local_APIC\n"); #else disable_local_APIC(); #endif @@ -593,7 +597,7 @@ void smp_send_stop(void) local_irq_disable(); #if 1 - printk("smp_send_stop disable_local_APIC\n"); + xxprint("smp_send_stop disable_local_APIC\n"); #else disable_local_APIC(); #endif @@ -608,7 +612,7 @@ void smp_send_stop(void) asmlinkage void smp_reschedule_interrupt(void) { #if 1 - printk("smp_reschedule_interrupt: ack_APIC_irq\n"); + xxprint("smp_reschedule_interrupt: ack_APIC_irq\n"); #else ack_APIC_irq(); #endif @@ -621,7 +625,7 @@ asmlinkage void smp_call_function_interrupt(void) int wait = call_data->wait; #if 1 - printk("smp_call_function_interrupt: ack_APIC_irq\n"); + xxprint("smp_call_function_interrupt: ack_APIC_irq\n"); #else ack_APIC_irq(); #endif diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smpboot.c b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smpboot.c index 6558024935..1843479a42 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smpboot.c +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smpboot.c @@ -51,16 +51,17 @@ #include #include -#if 0 +#if 1 +#define Dprintk(args...) +#define xxprint(msg) HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg) +#else #include #endif #include #include -#if 0 /* Set if we find a B stepping CPU */ static int __initdata smp_b_stepping; -#endif /* Number of siblings per CPU package */ int smp_num_siblings = 1; @@ -113,7 +114,14 @@ static unsigned long __init setup_trampoline(void) void __init smp_alloc_memory(void) { #if 1 - printk("smp_alloc_memory\n"); + int cpu; + + xxprint("smp_alloc_memory\n"); + for (cpu = 1; cpu < NR_CPUS; cpu++) { + cpu_gdt_descr[cpu].address = (unsigned long) + alloc_bootmem_low_pages(PAGE_SIZE); + /* XXX free unused pages later */ + } #else trampoline_base = (void *) alloc_bootmem_low_pages(PAGE_SIZE); /* @@ -134,7 +142,6 @@ void __init smp_alloc_memory(void) * a given CPU */ -#if 0 static void __init smp_store_cpu_info(int id) { struct cpuinfo_x86 *c = cpu_data + id; @@ -187,7 +194,6 @@ static void __init smp_store_cpu_info(int id) valid_k7: ; } -#endif #if 0 /* @@ -328,18 +334,16 @@ static void __init synchronize_tsc_ap (void) #undef NR_LOOPS extern void calibrate_delay(void); +#endif static atomic_t init_deasserted; -#endif void __init smp_callin(void) { -#if 1 - printk("smp_callin\n"); -#else int cpuid, phys_id; unsigned long timeout; +#if 0 /* * If waken up by an INIT in an 82489DX configuration * we may get here before an INIT-deassert IPI reaches @@ -347,11 +351,12 @@ void __init smp_callin(void) * lock up on an APIC access. */ wait_for_init_deassert(&init_deasserted); +#endif /* * (This works even if the APIC is not enabled.) */ - phys_id = GET_APIC_ID(apic_read(APIC_ID)); + phys_id = smp_processor_id(); cpuid = smp_processor_id(); if (cpu_isset(cpuid, cpu_callin_map)) { printk("huh, phys CPU#%d, CPU#%d already present??\n", @@ -387,6 +392,7 @@ void __init smp_callin(void) BUG(); } +#if 0 /* * the boot CPU has finished the init stage and is spinning * on callin_map until we finish. We are free to set up this @@ -405,6 +411,7 @@ void __init smp_callin(void) * Get our bogomips. */ calibrate_delay(); +#endif Dprintk("Stack at about %p\n",&cpuid); /* @@ -412,13 +419,16 @@ void __init smp_callin(void) */ smp_store_cpu_info(cpuid); +#if 0 disable_APIC_timer(); local_irq_disable(); +#endif /* * Allow the master to continue. */ cpu_set(cpuid, cpu_callin_map); +#if 0 /* * Synchronize the TSC with the BP */ @@ -436,8 +446,48 @@ extern int cpu_idle(void); */ int __init start_secondary(void *unused) { + /* + * Dont put anything before smp_callin(), SMP + * booting is too fragile that we want to limit the + * things done here to the most necessary things. + */ + cpu_init(); + smp_callin(); + while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) + rep_nop(); #if 1 - printk("start_secondary\n"); + if (0) { + char *msg = "start_secondary\n"; + char *msg2 = "delay2\n"; + int timeout; + (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg); + for (timeout = 0; timeout < 50000; timeout++) { + udelay(100); + if (timeout == 20000) { + (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg2), msg2); + timeout = 0; + } + } + } + // enable_APIC_timer(); + /* + * low-memory mappings have been cleared, flush them from + * the local TLBs too. + */ + // local_flush_tlb(); + cpu_set(smp_processor_id(), cpu_online_map); + wmb(); + if (10) { + char *msg2 = "delay2\n"; + int timeout; + for (timeout = 0; timeout < 50000; timeout++) { + udelay(1000); + if (timeout == 2000) { + (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg2), msg2); + timeout = 0; + } + } + } return cpu_idle(); #else /* @@ -531,7 +581,7 @@ u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; void map_cpu_to_logical_apicid(void) { #if 1 - printk("map_cpu_to_logical_apicid\n"); + xxprint("map_cpu_to_logical_apicid\n"); #else int cpu = smp_processor_id(); int apicid = logical_smp_processor_id(); @@ -642,7 +692,7 @@ static int __init wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) { #if 1 - printk("wakeup_secondary_cpu\n"); + xxprint("wakeup_secondary_cpu\n"); return 0; #else unsigned long send_status = 0, accept_status = 0; @@ -780,7 +830,6 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) extern cpumask_t cpu_initialized; -#if 0 static int __init do_boot_cpu(int apicid) /* * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad @@ -792,7 +841,14 @@ static int __init do_boot_cpu(int apicid) unsigned long boot_error; int timeout, cpu; unsigned long start_eip; +#if 0 unsigned short nmi_high = 0, nmi_low = 0; +#endif + full_execution_context_t ctxt; + extern void startup_32_smp(void); + extern void hypervisor_callback(void); + extern void failsafe_callback(void); + int i; cpu = ++cpucount; /* @@ -804,7 +860,7 @@ static int __init do_boot_cpu(int apicid) panic("failed fork for CPU %d", cpu); idle->thread.eip = (unsigned long) start_secondary; /* start_eip had better be page-aligned! */ - start_eip = setup_trampoline(); + start_eip = (unsigned long)startup_32_smp; /* So we see what's up */ printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip); @@ -820,6 +876,107 @@ static int __init do_boot_cpu(int apicid) atomic_set(&init_deasserted, 0); +#if 1 + if (cpu_gdt_descr[0].size > PAGE_SIZE) + BUG(); + cpu_gdt_descr[cpu].size = cpu_gdt_descr[0].size; + memcpy((void *)cpu_gdt_descr[cpu].address, + (void *)cpu_gdt_descr[0].address, cpu_gdt_descr[0].size); + memset((char *)cpu_gdt_descr[cpu].address + + FIRST_RESERVED_GDT_ENTRY * 8, 0, + NR_RESERVED_GDT_ENTRIES * 8); + + memset(&ctxt, 0, sizeof(ctxt)); + + ctxt.cpu_ctxt.ds = __USER_DS; + ctxt.cpu_ctxt.es = __USER_DS; + ctxt.cpu_ctxt.fs = 0; + ctxt.cpu_ctxt.gs = 0; + ctxt.cpu_ctxt.ss = __KERNEL_DS; + ctxt.cpu_ctxt.cs = __KERNEL_CS; + ctxt.cpu_ctxt.eip = start_eip; + ctxt.cpu_ctxt.esp = idle->thread.esp; + ctxt.cpu_ctxt.eflags = (1<<9) | (1<<2); + + /* FPU is set up to default initial state. */ + memset(ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt)); + + /* Virtual IDT is empty at start-of-day. */ + for ( i = 0; i < 256; i++ ) + { + ctxt.trap_ctxt[i].vector = i; + ctxt.trap_ctxt[i].cs = FLAT_GUESTOS_CS; + } + ctxt.fast_trap_idx = 0; + + /* No LDT. */ + ctxt.ldt_ents = 0; + + { + unsigned long va; + int f; + + for (va = cpu_gdt_descr[cpu].address, f = 0; + va < cpu_gdt_descr[cpu].address + cpu_gdt_descr[cpu].size; + va += PAGE_SIZE, f++) { + ctxt.gdt_frames[f] = virt_to_machine(va) >> PAGE_SHIFT; + protect_page(swapper_pg_dir, (void *)va, PROT_ON); + } + ctxt.gdt_ents = cpu_gdt_descr[cpu].size / 8; + flush_page_update_queue(); + } + + /* Ring 1 stack is the initial stack. */ + ctxt.guestos_ss = __KERNEL_DS; + ctxt.guestos_esp = idle->thread.esp; + + /* Callback handlers. */ + ctxt.event_callback_cs = __KERNEL_CS; + ctxt.event_callback_eip = (unsigned long)hypervisor_callback; + ctxt.failsafe_callback_cs = __KERNEL_CS; + ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback; + + ctxt.pt_base = (unsigned long)virt_to_machine(swapper_pg_dir); + + boot_error = HYPERVISOR_boot_vcpu(cpu, &ctxt); + + if (!boot_error) { + /* + * allow APs to start initializing. + */ + Dprintk("Before Callout %d.\n", cpu); + cpu_set(cpu, cpu_callout_map); + Dprintk("After Callout %d.\n", cpu); + + /* + * Wait 5s total for a response + */ + for (timeout = 0; timeout < 50000; timeout++) { + if (cpu_isset(cpu, cpu_callin_map)) + break; /* It has booted */ + udelay(100); + } + + if (cpu_isset(cpu, cpu_callin_map)) { + /* number CPUs logically, starting from 1 (BSP is 0) */ + Dprintk("OK.\n"); + printk("CPU%d: ", cpu); + print_cpu_info(&cpu_data[cpu]); + Dprintk("CPU has booted.\n"); + } else { + boot_error= 1; + } + } + x86_cpu_to_apicid[cpu] = apicid; + if (boot_error) { + /* Try to put things back the way they were before ... */ + // unmap_cpu_to_logical_apicid(cpu); + cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */ + cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */ + cpucount--; + } + +#else Dprintk("Setting warm reset code and vector.\n"); store_NMI_vector(&nmi_high, &nmi_low); @@ -877,14 +1034,13 @@ static int __init do_boot_cpu(int apicid) /* mark "stuck" area as not stuck */ *((volatile unsigned long *)trampoline_base) = 0; +#endif return boot_error; } cycles_t cacheflush_time; -#endif unsigned long cache_decay_ticks; -#if 0 static void smp_tune_scheduling (void) { @@ -931,6 +1087,7 @@ static void smp_tune_scheduling (void) * Cycle through the processors sending APIC IPIs to boot each. */ +#if 0 static int boot_cpu_logical_apicid; #endif /* Where the IO area was mapped on multiquad, always 0 otherwise */ @@ -940,11 +1097,11 @@ cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; static void __init smp_boot_cpus(unsigned int max_cpus) { -#if 1 - printk("smp_boot_cpus %d\n", max_cpus); -#else - int apicid, cpu, bit, kicked; + int cpu, kicked; unsigned long bogosum = 0; +#if 0 + int apicid, bit; +#endif /* * Setup boot CPU information @@ -953,9 +1110,15 @@ static void __init smp_boot_cpus(unsigned int max_cpus) printk("CPU%d: ", 0); print_cpu_info(&cpu_data[0]); +#if 0 boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); boot_cpu_logical_apicid = logical_smp_processor_id(); x86_cpu_to_apicid[0] = boot_cpu_physical_apicid; +#else + // boot_cpu_physical_apicid = 0; + // boot_cpu_logical_apicid = 0; + x86_cpu_to_apicid[0] = 0; +#endif current_thread_info()->cpu = 0; smp_tune_scheduling(); @@ -966,17 +1129,20 @@ static void __init smp_boot_cpus(unsigned int max_cpus) * If we couldn't find an SMP configuration at boot time, * get out of here now! */ - if (!smp_found_config && !acpi_lapic) { + if (!smp_found_config /* && !acpi_lapic) */) { printk(KERN_NOTICE "SMP motherboard not detected.\n"); smpboot_clear_io_apic_irqs(); +#if 0 phys_cpu_present_map = physid_mask_of_physid(0); if (APIC_init_uniprocessor()) printk(KERN_NOTICE "Local APIC not detected." " Using dummy APIC emulation.\n"); +#endif map_cpu_to_logical_apicid(); return; } +#if 0 /* * Should not be necessary because the MP table should list the boot * CPU too, but we do it for the sake of robustness anyway. @@ -1001,18 +1167,22 @@ static void __init smp_boot_cpus(unsigned int max_cpus) } verify_local_APIC(); +#endif /* * If SMP should be disabled, then really disable it! */ if (!max_cpus) { - smp_found_config = 0; + HYPERVISOR_shared_info->n_vcpu = 1; printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n"); smpboot_clear_io_apic_irqs(); +#if 0 phys_cpu_present_map = physid_mask_of_physid(0); +#endif return; } +#if 0 connect_bsp_APIC(); setup_local_APIC(); map_cpu_to_logical_apicid(); @@ -1028,32 +1198,29 @@ static void __init smp_boot_cpus(unsigned int max_cpus) * clustered apic ID. */ Dprintk("CPU present map: %lx\n", physids_coerce(phys_cpu_present_map)); +#endif + Dprintk("CPU present map: %lx\n", + (1UL << HYPERVISOR_shared_info->n_vcpu) - 1); kicked = 1; - for (bit = 0; kicked < NR_CPUS && bit < MAX_APICS; bit++) { - apicid = cpu_present_to_apicid(bit); - /* - * Don't even attempt to start the boot CPU! - */ - if ((apicid == boot_cpu_apicid) || (apicid == BAD_APICID)) - continue; - - if (!check_apicid_present(bit)) - continue; + for (cpu = 1; kicked < NR_CPUS && + cpu < HYPERVISOR_shared_info->n_vcpu; cpu++) { if (max_cpus <= cpucount+1) continue; - if (do_boot_cpu(apicid)) + if (do_boot_cpu(cpu)) printk("CPU #%d not responding - cannot use it.\n", - apicid); + cpu); else ++kicked; } +#if 0 /* * Cleanup possible dangling ends... */ smpboot_restore_warm_reset_vector(); +#endif /* * Allow the user to impress friends. @@ -1117,6 +1284,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings); } +#if 0 if (nmi_watchdog == NMI_LOCAL_APIC) check_nmi_watchdog(); @@ -1130,6 +1298,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) if (cpu_has_tsc && cpucount && cpu_khz) synchronize_tsc_bp(); #endif + xxprint("smp_boot_cpus done\n"); } /* These are wrappers to interface to the new boot process. Someone @@ -1147,6 +1316,7 @@ void __devinit smp_prepare_boot_cpu(void) int __devinit __cpu_up(unsigned int cpu) { + xxprint("__cpu_up\n"); /* This only works at boot for x86. See "rewrite" above. */ if (cpu_isset(cpu, smp_commenced_mask)) { local_irq_enable(); @@ -1164,13 +1334,13 @@ int __devinit __cpu_up(unsigned int cpu) cpu_set(cpu, smp_commenced_mask); while (!cpu_isset(cpu, cpu_online_map)) mb(); + xxprint("__cpu_up ok\n"); return 0; } void __init smp_cpus_done(unsigned int max_cpus) { #if 1 - printk("smp_cpus_done %d\n", max_cpus); #else #ifdef CONFIG_X86_IO_APIC setup_ioapic_dest(); @@ -1186,7 +1356,7 @@ void __init smp_cpus_done(unsigned int max_cpus) void __init smp_intr_init(void) { #if 1 - printk("smp_intr_init\n"); + xxprint("smp_intr_init\n"); #else /* * IRQ0 must be given a fixed assignment and initialized, diff --git a/linux-2.6.9-xen-sparse/arch/xen/kernel/evtchn.c b/linux-2.6.9-xen-sparse/arch/xen/kernel/evtchn.c index 28dca535d9..018f7aeb92 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/kernel/evtchn.c +++ b/linux-2.6.9-xen-sparse/arch/xen/kernel/evtchn.c @@ -42,6 +42,8 @@ #include #include #include +#define XEN_EVTCHN_MASK_OPS +#include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) EXPORT_SYMBOL(force_evtchn_callback); @@ -89,14 +91,15 @@ void evtchn_do_upcall(struct pt_regs *regs) int irq; unsigned long flags; shared_info_t *s = HYPERVISOR_shared_info; + vcpu_info_t *vcpu_info = &s->vcpu_data[smp_processor_id()]; local_irq_save(flags); - while ( s->vcpu_data[0].evtchn_upcall_pending ) + while ( vcpu_info->evtchn_upcall_pending ) { - s->vcpu_data[0].evtchn_upcall_pending = 0; + vcpu_info->evtchn_upcall_pending = 0; /* NB. No need for a barrier here -- XCHG is a barrier on x86. */ - l1 = xchg(&s->evtchn_pending_sel, 0); + l1 = xchg(&vcpu_info->evtchn_pending_sel, 0); while ( (l1i = ffs(l1)) != 0 ) { l1i--; @@ -411,6 +414,22 @@ static struct irqaction misdirect_action = { NULL }; +static irqreturn_t xen_dbg(int irq, void *dev_id, struct pt_regs *regs) +{ + char *msg = "debug\n"; + (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg); + return IRQ_HANDLED; +} + +static struct irqaction xen_action = { + xen_dbg, + SA_INTERRUPT, + CPU_MASK_CPU0, + "xen-dbg", + NULL, + NULL +}; + void irq_suspend(void) { int pirq, virq, irq, evtchn; @@ -508,6 +527,9 @@ void __init init_IRQ(void) (void)setup_irq(bind_virq_to_irq(VIRQ_MISDIRECT), &misdirect_action); + printk("debug_int\n"); + (void)setup_irq(bind_virq_to_irq(VIRQ_DEBUG), &xen_action); + /* This needs to be done early, but after the IRQ subsystem is alive. */ ctrl_if_init(); } diff --git a/linux-2.6.9-xen-sparse/drivers/xen/blkback/blkback.c b/linux-2.6.9-xen-sparse/drivers/xen/blkback/blkback.c index 6d201022d2..08e118d286 100644 --- a/linux-2.6.9-xen-sparse/drivers/xen/blkback/blkback.c +++ b/linux-2.6.9-xen-sparse/drivers/xen/blkback/blkback.c @@ -11,6 +11,7 @@ */ #include "common.h" +#include /* * These are rather arbitrary. They are fairly large because adjacent requests diff --git a/linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c index b98e7c37a9..0003aee737 100644 --- a/linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -44,6 +44,7 @@ #include #include #include +#include typedef unsigned char byte; /* from linux/ide.h */ diff --git a/linux-2.6.9-xen-sparse/drivers/xen/evtchn/evtchn.c b/linux-2.6.9-xen-sparse/drivers/xen/evtchn/evtchn.c index 60170e12dd..588a28a846 100644 --- a/linux-2.6.9-xen-sparse/drivers/xen/evtchn/evtchn.c +++ b/linux-2.6.9-xen-sparse/drivers/xen/evtchn/evtchn.c @@ -43,6 +43,7 @@ #include #include #include +#define XEN_EVTCHN_MASK_OPS #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) diff --git a/linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c index 143ccff364..528f3636ef 100644 --- a/linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c @@ -11,6 +11,7 @@ */ #include "common.h" +#include static void netif_page_release(struct page *page); static void netif_skb_release(struct sk_buff *skb); diff --git a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/smpboot_hooks.h b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/smpboot_hooks.h index 9885c24ab9..421a81f17b 100644 --- a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/smpboot_hooks.h +++ b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/smpboot_hooks.h @@ -54,3 +54,6 @@ static inline void smpboot_setup_io_apic(void) setup_IO_APIC(); #endif } + + +#define smp_found_config (HYPERVISOR_shared_info->n_vcpu > 1) diff --git a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/system.h b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/system.h index 133f1eaf49..bcb1a9e7c2 100644 --- a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/system.h +++ b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/system.h @@ -8,7 +8,6 @@ #include #include #include -#include #ifdef __KERNEL__ diff --git a/linux-2.6.9-xen-sparse/include/asm-xen/evtchn.h b/linux-2.6.9-xen-sparse/include/asm-xen/evtchn.h index bf27321263..1bc1fc9a49 100644 --- a/linux-2.6.9-xen-sparse/include/asm-xen/evtchn.h +++ b/linux-2.6.9-xen-sparse/include/asm-xen/evtchn.h @@ -36,20 +36,20 @@ #include #include #include +#include /* * LOW-LEVEL DEFINITIONS */ -/* Force a proper event-channel callback from Xen. */ -void force_evtchn_callback(void); - /* Entry point for notifications into Linux subsystems. */ void evtchn_do_upcall(struct pt_regs *regs); /* Entry point for notifications into the userland character device. */ void evtchn_device_upcall(int port); +#ifdef XEN_EVTCHN_MASK_OPS + static inline void mask_evtchn(int port) { shared_info_t *s = HYPERVISOR_shared_info; @@ -59,6 +59,7 @@ static inline void mask_evtchn(int port) static inline void unmask_evtchn(int port) { shared_info_t *s = HYPERVISOR_shared_info; + vcpu_info_t *vcpu_info = &s->vcpu_data[smp_processor_id()]; synch_clear_bit(port, &s->evtchn_mask[0]); @@ -67,14 +68,16 @@ static inline void unmask_evtchn(int port) * a real IO-APIC we 'lose the interrupt edge' if the channel is masked. */ if ( synch_test_bit (port, &s->evtchn_pending[0]) && - !synch_test_and_set_bit(port>>5, &s->evtchn_pending_sel) ) + !synch_test_and_set_bit(port>>5, &vcpu_info->evtchn_pending_sel) ) { - s->vcpu_data[0].evtchn_upcall_pending = 1; - if ( !s->vcpu_data[0].evtchn_upcall_mask ) + vcpu_info->evtchn_upcall_pending = 1; + if ( !vcpu_info->evtchn_upcall_mask ) force_evtchn_callback(); } } +#endif /* XEN_EVTCHN_MASK_OPS */ + static inline void clear_evtchn(int port) { shared_info_t *s = HYPERVISOR_shared_info; diff --git a/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h b/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h index caca29bd86..67336b1ab8 100644 --- a/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h +++ b/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h @@ -48,6 +48,10 @@ union xen_start_info_union extern union xen_start_info_union xen_start_info_union; #define xen_start_info (xen_start_info_union.xen_start_info) +/* arch/xen/kernel/evtchn.c */ +/* Force a proper event-channel callback from Xen. */ +void force_evtchn_callback(void); + /* arch/xen/kernel/process.c */ void xen_cpu_idle (void); @@ -647,4 +651,20 @@ HYPERVISOR_vm_assist( return ret; } +static inline int +HYPERVISOR_boot_vcpu( + unsigned long vcpu, full_execution_context_t *ctxt) +{ + int ret; + unsigned long ign1, ign2; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2) + : "0" (__HYPERVISOR_boot_vcpu), "1" (vcpu), "2" (ctxt) + : "memory"); + + return ret; +} + #endif /* __HYPERVISOR_H__ */ diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index 1db39317de..55f9717802 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -94,7 +94,8 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) /* The new domain's shared-info frame number. */ unsigned long shared_info_frame; - unsigned char shared_info[PAGE_SIZE]; /* saved contents from file */ + unsigned char shared_info_page[PAGE_SIZE]; /* saved contents from file */ + shared_info_t *shared_info = (shared_info_t *)shared_info_page; /* A copy of the CPU context of the guest. */ full_execution_context_t ctxt; @@ -525,8 +526,8 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) } } - if ( xcio_read(ioctxt, &ctxt, sizeof(ctxt)) || - xcio_read(ioctxt, shared_info, PAGE_SIZE) ) + if ( xcio_read(ioctxt, &ctxt, sizeof(ctxt)) || + xcio_read(ioctxt, shared_info_page, PAGE_SIZE) ) { xcio_error(ioctxt, "Error when reading from state file"); goto out; @@ -577,9 +578,10 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT; /* clear any pending events and the selector */ - memset(&(((shared_info_t *)shared_info)->evtchn_pending[0]), - 0, sizeof (((shared_info_t *)shared_info)->evtchn_pending)+ - sizeof(((shared_info_t *)shared_info)->evtchn_pending_sel)); + memset(&(shared_info->evtchn_pending[0]), 0, + sizeof (shared_info->evtchn_pending)); + for ( i = 0; i < MAX_VIRT_CPUS; i++ ) + shared_info->vcpu_data[i].evtchn_pending_sel = 0; /* Copy saved contents of shared-info page. No checking needed. */ ppage = xc_map_foreign_range( diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 822ab13a45..86c6118ee6 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -550,7 +550,8 @@ void domain_relinquish_memory(struct domain *d) * Relinquish GDT mappings. No need for explicit unmapping of the LDT as * it automatically gets squashed when the guest's mappings go away. */ - destroy_gdt(d); + for_each_exec_domain(d, ed) + destroy_gdt(ed); /* Relinquish every page of memory. */ relinquish_list(d, &d->xenpage_list); diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index 67b2009245..eafc94fe09 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -621,6 +621,7 @@ ENTRY(hypercall_table) .long SYMBOL_NAME(do_grant_table_op) /* 20 */ .long SYMBOL_NAME(do_vm_assist) .long SYMBOL_NAME(do_update_va_mapping_otherdomain) + .long SYMBOL_NAME(do_boot_vcpu) .rept NR_hypercalls-((.-hypercall_table)/4) .long SYMBOL_NAME(do_ni_hypercall) .endr diff --git a/xen/arch/x86/x86_32/mm.c b/xen/arch/x86/x86_32/mm.c index ac800e2d50..ce96f4db3f 100644 --- a/xen/arch/x86/x86_32/mm.c +++ b/xen/arch/x86/x86_32/mm.c @@ -240,19 +240,16 @@ int check_descriptor(unsigned long *d) } -void destroy_gdt(struct domain *d) +void destroy_gdt(struct exec_domain *ed) { - struct exec_domain *ed; int i; unsigned long pfn; - for_each_exec_domain(d, ed) { - for ( i = 0; i < 16; i++ ) - { - if ( (pfn = l1_pgentry_to_pagenr(ed->mm.perdomain_pt[i])) != 0 ) - put_page_and_type(&frame_table[pfn]); - ed->mm.perdomain_pt[i] = mk_l1_pgentry(0); - } + for ( i = 0; i < 16; i++ ) + { + if ( (pfn = l1_pgentry_to_pagenr(ed->mm.perdomain_pt[i])) != 0 ) + put_page_and_type(&frame_table[pfn]); + ed->mm.perdomain_pt[i] = mk_l1_pgentry(0); } } @@ -302,7 +299,7 @@ long set_gdt(struct exec_domain *ed, unmap_domain_mem(vgdt); /* Tear down the old GDT. */ - destroy_gdt(d); + destroy_gdt(ed); /* Install the new GDT. */ for ( i = 0; i < nr_pages; i++ ) diff --git a/xen/common/domain.c b/xen/common/domain.c index 28eb98bedd..d35d19d43c 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -62,7 +63,7 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu) arch_do_createdomain(ed); - sched_add_domain(d); + sched_add_domain(ed); write_lock(&domlist_lock); pd = &domain_list; /* NB. domain_list maintained in order of dom_id. */ @@ -77,7 +78,7 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu) } else { - sched_add_domain(d); + sched_add_domain(ed); } return d; @@ -288,6 +289,76 @@ int final_setup_guestos(struct domain *p, dom0_builddomain_t *builddomain) return rc; } +extern xmem_cache_t *exec_domain_struct_cachep; + +/* + * final_setup_guestos is used for final setup and launching of domains other + * than domain 0. ie. the domains that are being built by the userspace dom0 + * domain builder. + */ +long do_boot_vcpu(unsigned long vcpu, full_execution_context_t *ctxt) +{ + struct domain *d = current->domain; + struct exec_domain *ed; + int rc = 0; + full_execution_context_t *c; + + if ( d->exec_domain[vcpu] != NULL ) + return EINVAL; + + if ( alloc_exec_domain_struct(d, vcpu) == NULL ) + return -ENOMEM; + + if ( (c = xmalloc(sizeof(*c))) == NULL ) + { + rc = -ENOMEM; + goto out; + } + + if ( copy_from_user(c, ctxt, sizeof(*c)) ) + { + rc = -EFAULT; + goto out; + } + + printk("do_boot_vcpu for dom %d vcpu %d\n", d->id, vcpu); + + ed = d->exec_domain[vcpu]; + + atomic_set(&ed->pausecnt, 0); + shadow_lock_init(ed); + + memcpy(&ed->thread, &idle0_exec_domain.thread, sizeof(ed->thread)); + + /* arch_do_createdomain */ + ed->mm.perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page(); + memset(ed->mm.perdomain_pt, 0, PAGE_SIZE); + machine_to_phys_mapping[virt_to_phys(ed->mm.perdomain_pt) >> + PAGE_SHIFT] = INVALID_P2M_ENTRY; + + sched_add_domain(ed); + + if ( (rc = arch_final_setup_guestos(ed, c)) != 0 ) + goto out; + + /* Set up the shared info structure. */ + update_dom_time(d); + + /* domain_unpause_by_systemcontroller */ + if ( test_and_clear_bit(EDF_CTRLPAUSE, &ed->ed_flags) ) + domain_wake(ed); + + xfree(c); + return 0; + + out: + if ( c != NULL ) + xfree(c); + xmem_cache_free(exec_domain_struct_cachep, d->exec_domain[vcpu]); + d->exec_domain[vcpu] = NULL; + return rc; +} + long vm_assist(struct domain *p, unsigned int cmd, unsigned int type) { if ( type > MAX_VMASST_TYPE ) diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c index c5ab06145a..90db32cc6c 100644 --- a/xen/common/keyhandler.c +++ b/xen/common/keyhandler.c @@ -100,15 +100,21 @@ void do_task_queues(unsigned char key) page->u.inuse.type_info); for_each_exec_domain ( d, ed ) { - printk("Guest: CPU %d [has=%c] flags=%lx " - "upcall_pend = %02x, upcall_mask = %02x\n", + printk("Guest: %p CPU %d [has=%c] flags=%lx " + "upcall_pend = %02x, upcall_mask = %02x\n", ed, ed->processor, test_bit(EDF_RUNNING, &ed->ed_flags) ? 'T':'F', ed->ed_flags, ed->vcpu_info->evtchn_upcall_pending, ed->vcpu_info->evtchn_upcall_mask); } - printk("Notifying guest...\n"); + ed = d->exec_domain[0]; + printk("Notifying guest... %d/%d\n", d->id, ed->eid); + printk("port %d/%d stat %d %d %d\n", + VIRQ_DEBUG, d->virq_to_evtchn[VIRQ_DEBUG], + test_bit(d->virq_to_evtchn[VIRQ_DEBUG], &d->shared_info->evtchn_pending[0]), + test_bit(d->virq_to_evtchn[VIRQ_DEBUG], &d->shared_info->evtchn_mask[0]), + test_bit(d->virq_to_evtchn[VIRQ_DEBUG]>>5, &ed->vcpu_info->evtchn_pending_sel)); send_guest_virq(d->exec_domain[0], VIRQ_DEBUG); } diff --git a/xen/common/sched_bvt.c b/xen/common/sched_bvt.c index 065b91949a..cacd7abb68 100644 --- a/xen/common/sched_bvt.c +++ b/xen/common/sched_bvt.c @@ -179,6 +179,7 @@ int bvt_alloc_task(struct exec_domain *ed) } ed->ed_sched_priv = &BVT_INFO(d)->ed_inf[ed->eid]; BVT_INFO(d)->ed_inf[ed->eid].inf = BVT_INFO(d); + BVT_INFO(d)->ed_inf[ed->eid].exec_domain = ed; return 0; } @@ -192,25 +193,28 @@ void bvt_add_task(struct exec_domain *d) ASSERT(inf != NULL); ASSERT(d != NULL); - inf->mcu_advance = MCU_ADVANCE; - inf->domain = d->domain; + if (d->eid == 0) { + inf->mcu_advance = MCU_ADVANCE; + inf->domain = d->domain; + inf->warpback = 0; + /* Set some default values here. */ + inf->warp = 0; + inf->warp_value = 0; + inf->warpl = MILLISECS(2000); + inf->warpu = MILLISECS(1000); + /* initialise the timers */ + init_ac_timer(&inf->warp_timer); + inf->warp_timer.cpu = d->processor; + inf->warp_timer.data = (unsigned long)inf; + inf->warp_timer.function = &warp_timer_fn; + init_ac_timer(&inf->unwarp_timer); + inf->unwarp_timer.cpu = d->processor; + inf->unwarp_timer.data = (unsigned long)inf; + inf->unwarp_timer.function = &unwarp_timer_fn; + } + einf->exec_domain = d; - inf->warpback = 0; - /* Set some default values here. */ - inf->warp = 0; - inf->warp_value = 0; - inf->warpl = MILLISECS(2000); - inf->warpu = MILLISECS(1000); - /* initialise the timers */ - init_ac_timer(&inf->warp_timer); - inf->warp_timer.cpu = d->processor; - inf->warp_timer.data = (unsigned long)inf; - inf->warp_timer.function = &warp_timer_fn; - init_ac_timer(&inf->unwarp_timer); - inf->unwarp_timer.cpu = d->processor; - inf->unwarp_timer.data = (unsigned long)inf; - inf->unwarp_timer.function = &unwarp_timer_fn; - + if ( d->domain->id == IDLE_DOMAIN_ID ) { einf->avt = einf->evt = ~0U; diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 96476a6ce4..748a226329 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -106,32 +106,67 @@ void free_domain_struct(struct domain *d) xmem_cache_free(domain_struct_cachep, d); } -struct domain *alloc_domain_struct(void) +struct exec_domain *alloc_exec_domain_struct(struct domain *d, + unsigned long vcpu) { - struct domain *d; - struct exec_domain *ed = NULL; + struct exec_domain *ed, *edc; - if ( (d = xmem_cache_alloc(domain_struct_cachep)) == NULL ) - return NULL; - - memset(d, 0, sizeof(*d)); + ASSERT( d->exec_domain[vcpu] == NULL ); if ( (ed = xmem_cache_alloc(exec_domain_struct_cachep)) == NULL ) - goto out; + return NULL; memset(ed, 0, sizeof(*ed)); - d->exec_domain[0] = ed; + d->exec_domain[vcpu] = ed; ed->domain = d; + ed->eid = vcpu; if ( SCHED_OP(alloc_task, ed) < 0 ) goto out; + if (vcpu != 0) { + ed->vcpu_info = &d->shared_info->vcpu_data[ed->eid]; + + for_each_exec_domain(d, edc) { + if (edc->ed_next_list == NULL || edc->ed_next_list->eid > vcpu) + break; + } + ed->ed_next_list = edc->ed_next_list; + edc->ed_next_list = ed; + + if (test_bit(EDF_CPUPINNED, &edc->ed_flags)) { + ed->processor = (edc->processor + 1) % smp_num_cpus; + set_bit(EDF_CPUPINNED, &ed->ed_flags); + } else { + ed->processor = (edc->processor + 1) % smp_num_cpus; /* XXX */ + } + } + + return ed; + + out: + d->exec_domain[vcpu] = NULL; + xmem_cache_free(exec_domain_struct_cachep, ed); + + return NULL; +} + +struct domain *alloc_domain_struct(void) +{ + struct domain *d; + + if ( (d = xmem_cache_alloc(domain_struct_cachep)) == NULL ) + return NULL; + + memset(d, 0, sizeof(*d)); + + if ( alloc_exec_domain_struct(d, 0) == NULL ) + goto out; + return d; out: - if ( ed ) - xmem_cache_free(exec_domain_struct_cachep, ed); xmem_cache_free(domain_struct_cachep, d); return NULL; } @@ -139,31 +174,32 @@ struct domain *alloc_domain_struct(void) /* * Add and remove a domain */ -void sched_add_domain(struct domain *d) +void sched_add_domain(struct exec_domain *ed) { - struct exec_domain *ed; + struct domain *d = ed->domain; - for_each_exec_domain(d, ed) { - /* Must be unpaused by control software to start execution. */ - set_bit(EDF_CTRLPAUSE, &ed->ed_flags); - } + /* Must be unpaused by control software to start execution. */ + set_bit(EDF_CTRLPAUSE, &ed->ed_flags); - if ( d->id != IDLE_DOMAIN_ID ) - { - /* Initialise the per-domain timer. */ - init_ac_timer(&d->timer); - d->timer.cpu = d->exec_domain[0]->processor; - d->timer.data = (unsigned long)d; - d->timer.function = &dom_timer_fn; - } - else + if (ed->eid == 0) { - schedule_data[d->exec_domain[0]->processor].idle = d->exec_domain[0]; + if ( d->id != IDLE_DOMAIN_ID ) + { + /* Initialise the per-domain timer. */ + init_ac_timer(&d->timer); + d->timer.cpu = ed->processor; + d->timer.data = (unsigned long)d; + d->timer.function = &dom_timer_fn; + } + else + { + schedule_data[ed->processor].idle = ed; + } } - SCHED_OP(add_task, d->exec_domain[0]); + SCHED_OP(add_task, ed); - TRACE_2D(TRC_SCHED_DOM_ADD, d->id, d); + TRACE_2D(TRC_SCHED_DOM_ADD, d->id, ed); } void sched_rem_domain(struct domain *d) diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index 2476314cfc..38110b94ee 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -420,7 +420,7 @@ static inline void write_ptbase(struct mm_struct *mm) #define GET_GDT_ENTRIES(_p) (((*(u16 *)((_p)->mm.gdt + 0))+1)>>3) #define GET_GDT_ADDRESS(_p) (*(unsigned long *)((_p)->mm.gdt + 2)) -void destroy_gdt(struct domain *d); +void destroy_gdt(struct exec_domain *d); long set_gdt(struct exec_domain *d, unsigned long *frames, unsigned int entries); diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index eafb7bd639..c4d2ffe8ea 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -48,6 +48,7 @@ #define __HYPERVISOR_grant_table_op 20 #define __HYPERVISOR_vm_assist 21 #define __HYPERVISOR_update_va_mapping_otherdomain 22 +#define __HYPERVISOR_boot_vcpu 23 /* * MULTICALLS @@ -287,6 +288,7 @@ typedef struct vcpu_info_st u8 evtchn_upcall_pending; u8 evtchn_upcall_mask; u8 pad0, pad1; + u32 evtchn_pending_sel; /* 132 */ } PACKED vcpu_info_t; /* @@ -331,7 +333,6 @@ typedef struct shared_info_st * word in the PENDING bitfield array. */ u32 evtchn_pending[32]; /* 4 */ - u32 evtchn_pending_sel; /* 132 */ u32 evtchn_mask[32]; /* 136 */ /* diff --git a/xen/include/xen/event.h b/xen/include/xen/event.h index 168c28185d..c59439608f 100644 --- a/xen/include/xen/event.h +++ b/xen/include/xen/event.h @@ -29,7 +29,7 @@ static inline void evtchn_set_pending(struct exec_domain *ed, int port) /* These three operations must happen in strict order. */ if ( !test_and_set_bit(port, &s->evtchn_pending[0]) && !test_bit (port, &s->evtchn_mask[0]) && - !test_and_set_bit(port>>5, &s->evtchn_pending_sel) ) + !test_and_set_bit(port>>5, &ed->vcpu_info->evtchn_pending_sel) ) { /* The VCPU pending flag must be set /after/ update to evtchn-pend. */ set_bit(0, &ed->vcpu_info->evtchn_upcall_pending); diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 2c28a4a639..e1e06d59f5 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -178,6 +178,9 @@ extern struct exec_domain *idle_task[NR_CPUS]; #define IDLE_DOMAIN_ID (0x7FFFU) #define is_idle_task(_p) (test_bit(DF_IDLETASK, &(_p)->d_flags)) +struct exec_domain *alloc_exec_domain_struct(struct domain *d, + unsigned long vcpu); + void free_domain_struct(struct domain *d); struct domain *alloc_domain_struct(); @@ -242,7 +245,7 @@ extern unsigned long wait_init_idle; #define set_current_state(_s) do { current->state = (_s); } while (0) void scheduler_init(void); void schedulers_start(void); -void sched_add_domain(struct domain *d); +void sched_add_domain(struct exec_domain *d); void sched_rem_domain(struct domain *d); long sched_ctl(struct sched_ctl_cmd *); long sched_adjdom(struct sched_adjdom_cmd *); -- 2.30.2